/* Copyright ©北京微利宝信息技术有限公司 right reserved.*/

package com.wlb365.doc.cfca;

import cfca.sadk.algorithm.common.Mechanism;
import cfca.sadk.lib.crypto.JCrypto;
import cfca.sadk.lib.crypto.Session;
import cfca.sadk.system.SADKDebugger;
import cfca.sadk.util.CertUtil;
import cfca.sadk.util.KeyUtil;
import cfca.sadk.util.Signature;
import cfca.sadk.x509.certificate.X509Cert;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;

/**
 * <p>
 * 概述： 华通银行软文签名工具-cfca
 * </p>
 *
 * @author 创建人：   ryl
 * @copyRight 所有权©：  北京微利宝信息技术有限公司  All right reserved.
 * @date 创建时间： 2018年8月29日 下午2:36:53
 */
@Slf4j
public class RSAP7SignatureUtils {

    //签名算法
    private final static String SIGN_ALGORITHM = Mechanism.SHA1_RSA;

    private static Session session = null;

    static {
        try {
            String deviceName = JCrypto.JSOFT_LIB;
            JCrypto.getInstance().initialize(deviceName, null);
            session = JCrypto.getInstance().openSession(deviceName);
        } catch (Exception e) {
            log.error("初始化签名工具异常：", e);
        }

    }

    /**
     * <p>
     * 概述： 签名
     * </p>
     *
     * @param data 签名数据
     * @return String   签文
     * @throws Exception
     * @author ryl
     * @date 2018年8月29日 下午2:48:37
     */
    public static String sign(String cer, String passwrod, String data) throws Exception {
        //步骤1 构建证书对象
        //String pfxFileData = "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";
        X509Cert signCert = CertUtil.getCertFromPFX(cer, passwrod);

        //步骤2 获得私钥对象
        PrivateKey privateKey = KeyUtil.getPrivateKeyFromPFX(cer, passwrod);

        //步骤3 P7消息签名
        Signature signKit = new Signature();
        byte[] sourceData = StringUtils.to10(data.getBytes(StandardCharsets.UTF_8)).getBytes(StandardCharsets.UTF_8);
        log.debug("============================================================================");
        log.debug("==> 签名算法：" + SIGN_ALGORITHM);
        log.debug("==> 签名明文：" + data);
        log.debug("==> 签名Hex码: " + SADKDebugger.dump(sourceData));
        log.debug("============================================================================");
        byte[] signedData = signKit.p7SignMessageDetach(SIGN_ALGORITHM, sourceData, privateKey, signCert, session);
        return new String(signedData);
    }

    /**
     * <p>
     * 概述： 核签
     * </p>
     *
     * @param base64P7SignedData 签文
     * @param data               核签数据
     * @return boolean false:失败 true:成功
     * @throws Exception
     * @author ryl
     * @date 2018年8月29日 下午2:49:32
     */
    public static boolean verify(String base64P7SignedData, String data) throws Exception {

        byte[] p7SignedData = base64P7SignedData.getBytes(StandardCharsets.UTF_8);

        //验签
        Signature signKit = new Signature();
        byte[] sourceData = StringUtils.to10(data.getBytes(StandardCharsets.UTF_8)).getBytes(StandardCharsets.UTF_8);
        boolean result = signKit.p7VerifyMessageDetach(sourceData, p7SignedData, session);

        log.debug("============================================================================");
        log.debug("==> 核签明文: " + data);
        log.debug("==> 核签Hex码: " + SADKDebugger.dump(sourceData));
        log.debug("==> 核签结果: " + result);
        log.debug("============================================================================");
        return result;
    }
}